package token

import (
	"time"

	"github.com/google/uuid"
	"github.com/infraboard/mcube/v2/exception"
	"github.com/infraboard/mcube/v2/tools/pretty"
)

func NewToken(refUserId string) *Token {
	aExpiredAt := time.Now().AddDate(0, 0, 1)
	rExpiredAt := time.Now().AddDate(0, 0, 7)
	return &Token{
		RefUserId:            refUserId,
		AccessToken:          uuid.NewString(),
		AccessTokenExpireAt:  &aExpiredAt,
		IssueAt:              time.Now(),
		RefreshToken:         uuid.NewString(),
		RefreshTokenExpireAt: &rExpiredAt,
	}
}

// 用户的身份令牌
type Token struct {
	// TokenId
	Id uint `json:"id" gorm:"primaryKey;column:id"`
	// 用户Id
	RefUserId string `json:"ref_user_id" gorm:"column:ref_user_id"`
	// 访问令牌
	AccessToken string `json:"access_token" gorm:"column:access_token;unique;index"`
	// 访问Token过期时间
	AccessTokenExpireAt *time.Time `json:"access_token_expire_at" gorm:"column:access_token_expire_at"`
	// 令牌办法的时间
	IssueAt time.Time `json:"issue_at" gorm:"column:issue_at"`

	// 刷新Token
	RefreshToken string `json:"refresh_token" gorm:"column:refresh_token;unique;index"`
	// 刷新Token过期时间
	RefreshTokenExpireAt *time.Time `json:"refresh_token_expire_at" gorm:"column:refresh_token_expire_at"`

	// 关联查询 需要查询出来
	RefUserName string `json:"ref_user_name" gorm:"-"`
}

func (r *Token) AccessTokenExpireTTL() int {
	if r.AccessTokenExpireAt == nil {
		return 0
	}
	return int(time.Until(*r.AccessTokenExpireAt).Seconds())
}

func (r *Token) String() string {
	return pretty.ToJSON(r)
}

func (t *Token) TableName() string {
	return "tokens"
}

func (r *Token) IsAccessTokenExpired() error {
	if r.AccessTokenExpireAt == nil {
		return nil
	}
	if time.Now().After(*r.AccessTokenExpireAt) {
		return exception.NewAccessTokenExpired("%s 已过期", r.AccessToken)
	}
	return nil
}

func (r *Token) IsRefreshTokenExpired() error {
	if r.RefreshTokenExpireAt == nil {
		return nil
	}
	if time.Now().After(*r.RefreshTokenExpireAt) {
		return exception.NewAccessTokenExpired("%s 已过期", r.RefreshTokenExpireAt)
	}
	return nil
}

func (t *Token) SetRefUserName(refUserName string) *Token {
	t.RefUserName = refUserName
	return t
}
